#include "Generate_C_std.h"
#include "Pattern_assign_var.h"

class Pattern_assign_expr_field_access : public Pattern_assign_var
{
public:
	Expr* rhs_pattern()
	{
		rhs = new Wildcard<Field_access>;
		return rhs;
	}

	void generate_code (Generate_C* gen)
	{
		VARIABLE_NAME* object_name;
		CLASS_NAME* class_name;
		FIELD_NAME* field_name;
		Variable_field* var_field;
 		
		object_name = dynamic_cast<VARIABLE_NAME*>(rhs->value->target);
 		class_name  = dynamic_cast<CLASS_NAME*>(rhs->value->target);
		field_name  = dynamic_cast<FIELD_NAME*>(rhs->value->field_name);
		var_field   = dynamic_cast<Variable_field*>(rhs->value->field_name);

		bool is_ref = agn->is_ref;
		VARIABLE_NAME* lhs = Pattern_assign_var::lhs->value;

		if (field_name != NULL)
		{
			if (object_name != NULL)
			{
				if (!is_ref)
					INST (buf, "field_access", lhs, object_name, field_name);
				else
					INST (buf, "field_access_ref", lhs, object_name, field_name);
			}
			else if (class_name != NULL)
			{
				if (!is_ref)
					INST (buf, "static_field_access", lhs, class_name, field_name);
				else
					INST (buf, "static_field_access_ref", lhs, class_name, field_name);
			}
			else
			{
				// Invalid target
				phc_unreachable();
			}
		}
		else if (var_field != NULL)
		{
			VARIABLE_NAME* var_field_name = var_field->variable_name;

			if (object_name != NULL)
			{
				if (!is_ref)
					INST (buf, "var_field_access", lhs, object_name, var_field_name);
				else
					INST (buf, "var_field_access_ref", lhs, object_name, var_field_name);
			}
			else if (class_name != NULL)
			{
				if (!is_ref)
					INST (buf, "var_static_field_access", lhs, class_name, var_field_name);
				else
					INST (buf, "var_static_field_access_ref", lhs, class_name, var_field_name);
			}
			else
			{
				// Invalid target
				phc_unreachable();
			}
		}
		else
		{
			// Invalid field name
			phc_unreachable();
		}
	}

protected:
	Wildcard<Field_access>* rhs;
};

CREATE(Pattern_assign_expr_field_access);
